#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include <iostream>
#include <math.h>

#define DIF_THRESH 120
#define LOW_THRESH 150
#define HEAD_THRESH 75

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    VideoCapture cap(0); // open the video camera no. 0

    if (!cap.isOpened())  // if not success, exit program
    {
        cout << "Cannot open the video cam" << endl;
        return -1;
    }

   double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
   double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

    cout << "Frame size : " << dWidth << " x " << dHeight << endl;

    namedWindow("Blocked", CV_WINDOW_AUTOSIZE);		//create a window 
	namedWindow("Live View", CV_WINDOW_AUTOSIZE);	//create a window 
	namedWindow("Gray View", CV_WINDOW_AUTOSIZE);	//create a window 
	namedWindow("Grad View", CV_WINDOW_AUTOSIZE);	//create a window 
	
	Mat liveFrame;
	cap.read(liveFrame);
	Mat grayFrame = liveFrame.clone();
	cvtColor(grayFrame, grayFrame, CV_BGR2GRAY); 
	Mat blockFrame = liveFrame.clone();
	cvtColor(blockFrame, blockFrame, CV_BGR2GRAY);
	Mat gradFrame = liveFrame.clone();
	cvtColor(gradFrame, gradFrame, CV_BGR2GRAY);

	double averageExposure = 0; 

	double frameCount = 1; 
    while (1)
    {
        bool bSuccess = cap.read(liveFrame); // read a new frame from video

		cvtColor(liveFrame, grayFrame, CV_BGR2GRAY);
		cvtColor(liveFrame, blockFrame, CV_BGR2GRAY);
		cvtColor(liveFrame, gradFrame, CV_BGR2GRAY);

		averageExposure = 0; 
		for(int i=0; i<480; i++)
			for(int j=0; j<640; j++)
				averageExposure += grayFrame.at<uchar>(i, j); 

		averageExposure /= dWidth * dHeight; 

		// Creates the blocked frames
		for(int i=0; i<480; i++)
		{
			for(int j=0; j<640; j++)
			{
				if(((grayFrame.at<uchar>(i, j) - averageExposure) > DIF_THRESH) && (grayFrame.at<uchar>(i, j) > LOW_THRESH))
				{
					blockFrame.at<uchar>(i, j) = 0;
					if(((grayFrame.at<uchar>(i, j) - averageExposure) - DIF_THRESH) > HEAD_THRESH)
						gradFrame.at<uchar>(i, j) = 0;
					else
						gradFrame.at<uchar>(i, j) = HEAD_THRESH - ((grayFrame.at<uchar>(i, j) - averageExposure) - DIF_THRESH);
				}
				else
				{
					blockFrame.at<uchar>(i, j) = 255;
					gradFrame.at<uchar>(i, j) = 255; 
				}
			}
		}

			



        if (!bSuccess) //if not success, break loop
        {
             cout << "Cannot read a frame from video stream" << endl;
             break;
        }

		 
        imshow("Blocked", blockFrame);		//show the frame in "MyVideo" window
		imshow("Gray View", grayFrame);		//show the frame in "MyVideo" window
		imshow("Live View", liveFrame);		//show the frame in "MyVideo" window
		imshow("Grad View", gradFrame);		//show the frame in "MyVideo" window

        if (waitKey(30) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
		{
            cout << "esc key is pressed by user" << endl;
            break; 
		}
    }
    return 0;

}